/// <reference path="_References.ts"/>

declare var soundManager;

class Game
{
    public game = this;

    public static DIRECTION =
    {
        UP: 8,
        RIGHT: 6,
        DOWN: 2,
        LEFT: 4
    };

    public static direction = Game.DIRECTION.RIGHT;

    public static speed = 100; //range 1 - 100 in milliseconds
    /* TODO:
    timePassed = 0, //time passed since game started
    pauseState = true, //boolean type (we want a game paused on start)
    */
    public static context;
    public static player;
    public static snake;
    public static snakeAI;
    public static powerup;
    public static frame;
    public static input;
    public static fps: Fps;

    public static sounds: { snakeMoveSound: any; snakeEatSound: any; snakeTickSound: any; } = { snakeMoveSound: null, snakeEatSound: null, snakeTickSound: null };
    public static start = () =>
    {
        Game.createCanvas();
        Game.terrain.elementWidth = Game.context.canvas.width / Game.terrain.width;
        Game.terrain.elementHeight = Game.context.canvas.height / Game.terrain.height;
        //var name = prompt('Player name:');
        Game.player = new Player('JohnDoe');
        Game.snake = new Snake(Math.floor(Game.terrain.width / 4));
        Game.snakeAI = new Snake(Math.floor(Game.terrain.width / 4));
        Game.powerup = new Powerup();
        Game.fps = new Fps();
        Game.frame = new Frame();
        Game.input = new Input();
        Frame.draw();
    };

    public restart = function ()
    {
        // TODO
    };

    public pauseToggle = function ()
    {
        // TODO, add the break!
    };

    public help = function ()
    {
        // TODO
    };

    public quit = function ()
    {
        // TODO
    };

    public static createCanvas = () =>
    {
        var canvas = document.createElement("canvas");
        var ratio = ((1 + Math.sqrt(5)) / 2);

        var width, widthSpace, height, heightSpace;
        if (window.innerWidth < window.innerHeight * ratio)
        {
            width = window.innerWidth - 30;
            widthSpace = (window.innerWidth - width) / 2;
            height = window.innerWidth / ratio;
            heightSpace = (window.innerHeight - height) / 2;
        }
        else
        {
            height = window.innerHeight - 30;
            heightSpace = (window.innerHeight - height) / 2;
            width = window.innerHeight * ratio;
            widthSpace = (window.innerWidth - width) / 2;
        }

        canvas.setAttribute("width", width);
        canvas.setAttribute("height", height);
        canvas.setAttribute("style", "position: absolute; x:0; y:0;border:1px solid black;padding:3px;"
            + "margin: " + heightSpace + "px " + widthSpace + "px " + heightSpace + "px " + widthSpace + "px;");
        document.body.appendChild(canvas);
        Game.context = canvas.getContext("2d");
    };

    public static drawPoint = (point, color) =>
    {
        Game.context.beginPath();
        Game.context.rect(point.x * Game.terrain.elementWidth,
            point.y * Game.terrain.elementHeight,
            Game.terrain.elementWidth,
            Game.terrain.elementHeight);
        Game.context.fillStyle = color;
        Game.context.fill();
    };

    public static terrain =
    {
        width: 39,
        height: 24,

        elementWidth: 0,
        elementHeight: 0,

        getCoordinates: function (point)
        {
            return new Point(Game.terrain.elementWidth * point.x, Game.terrain.elementHeight * point.y);
        },

        getAdiacent: function (point, dir)
        {
            var newPoint = new Point(point.x, point.y);

            switch (dir)
            {
                case Game.DIRECTION.UP:
                    if (point.y === 0)
                        newPoint.y = Game.terrain.height - 1;
                    else
                        newPoint.y--;
                    break;

                case Game.DIRECTION.DOWN:
                    if (point.y == Game.terrain.height - 1)
                        newPoint.y = 0;
                    else
                        newPoint.y++;
                    break;

                case Game.DIRECTION.RIGHT:
                    if (point.x == Game.terrain.width - 1)
                        newPoint.x = 0;
                    else
                        newPoint.x++;
                    break;

                case Game.DIRECTION.LEFT:
                    if (point.x === 0)
                        newPoint.x = Game.terrain.width - 1;
                    else
                        newPoint.x--;
                    break;
            }

            return newPoint;
        },

        draw: function ()
        {
            var lineWidth = 0.001;
            var strokeStyle = "#00E2F2";
            var i;
            for (i = 0; i <= this.width; i++)
            {
                Game.context.moveTo(i / this.width * Game.context.canvas.width, 0);
                Game.context.lineTo(i / this.width * Game.context.canvas.width, Game.context.canvas.height);
                Game.context.strokeStyle = strokeStyle;
                Game.context.lineWidth = lineWidth;
                Game.context.stroke();
            }

            for (i = 0; i <= this.height; i++)
            {
                Game.context.moveTo(0, i / this.height * Game.context.canvas.height);
                Game.context.lineTo(Game.context.canvas.width, i / this.height * Game.context.canvas.height);
                Game.context.strokeStyle = strokeStyle;
                Game.context.lineWidth = lineWidth;
                Game.context.stroke();
            }
        }
    };

    public static pad(number, length)
    {
        var str = '' + number;
        while (str.length < length)
        {
            str = '0' + str;
        }

        return str;
    }

    constructor()
    {
        soundManager.audioFormats.mp3.required = false;
        soundManager.preferFlash = false;
        soundManager.autoLoad = true;
        soundManager.defaultOptions.volume = 20;

        soundManager.onready(() =>
        {
            Game.sounds.snakeTickSound = soundManager.createSound(
            {
                id: 'snakeTick',
                url: ['sounds/snakeTick.mp3', 'sounds/snakeTick.ogg']//,
                //onfinish: function ()
                //{
                //    var date = new Date();
                //    console.error("sound ended:   " + date.getSeconds() + "." + Game.pad(date.getMilliseconds(), 3));
                //}
            });

            Game.sounds.snakeMoveSound = soundManager.createSound({
                id: 'snakeMove',
                url: ['sounds/snakeMove.mp3', 'sounds/snakeMove.ogg']
            });

            Game.sounds.snakeEatSound = soundManager.createSound({
                id: 'snakeEat',
                url: ['sounds/snakeEat.mp3', 'sounds/snakeEat.ogg']
            });

            //game.sounds.startingSound = soundManager.createSound({
            //    id: 'startingSound',
            //    url: 'audio/gameStart.mp3'
            //});

            //startingSound.play(); TODO need to find a less annoying starting sound

            if (document.readyState != "complete")
                window.onload = Game.start;
            else
                Game.start();
        });

        soundManager.ontimeout(() =>
        {
            alert('soundmanager2 load failed!');
        });
    }
}